package threadDemo;

import java.util.function.IntConsumer;

public class FizzBuzzDemo {
    public static void main(String[] args) {
        FizzBuzz demo = new FizzBuzz(15);
        StringBuffer br = new StringBuffer("");
        new Thread(() -> {
            try {
                demo.buzz(new Runnable() {
                    @Override
                    public void run() {
                        System.out.print("buzz");
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                demo.fizz(new Runnable() {
                    @Override
                    public void run() {
                        System.out.print("fizz");
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                demo.fizzbuzz(new Runnable() {
                    @Override
                    public void run() {
                        System.out.print("fizzbuzz");
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(() -> {
            try {
                demo.number(new IntConsumer() {
                    @Override
                    public void accept(int value) {
                        System.out.print(value);
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

class FizzBuzz {
    private int n;
    private int count = 1;

    public FizzBuzz(int n) {
        this.n = n;
    }

    // printFizz.run() outputs "fizz".  被3整除
    public synchronized void fizz(Runnable printFizz) throws InterruptedException {
        while (count <= n) {
            if (count % 3 != 0 || count % 5 == 0) {
                this.wait();
                continue;
            }
            printFizz.run();
            count += 1;
            notifyAll();
        }
    }

    // printBuzz.run() outputs "buzz".  被5整除
    public synchronized void buzz(Runnable printBuzz) throws InterruptedException {
        while (count <= n) {
            if (count % 3 == 0 || count % 5 != 0) {
                this.wait();
                continue;
            }
            printBuzz.run();
            count += 1;
            notifyAll();
        }
    }

    // printFizzBuzz.run() outputs "fizzbuzz".
    public synchronized void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
        while (count <= n) {
            if (count % 15 != 0) {
                this.wait();
                continue;
            }
            printFizzBuzz.run();
            count += 1;
            notifyAll();
        }
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public synchronized void number(IntConsumer printNumber) throws InterruptedException {
        while (count <= n) {
            if (count % 3 == 0 || count % 5 == 0) {
                this.wait();
                continue;
            }
            printNumber.accept(count);
            count += 1;
            notifyAll();
        }
    }
}